<!DOCTYPE html>
<html>
  <head>
    <title>TransitionSyncTween</title>
    <script src="d3.min.js"></script>
  </head>
  <body>
    <svg width="1600" height="800" id="mainsvg" class="svgs" style='display: block; margin: 0 auto;'></svg>
    <script>
        const data = [{name: 'Shao-Kui', value:6},
        {name:'Wen-Yang', value:6}, {name:'Yi Ke', value:16}, {name:'Liang Yuan', value: 10}, 
        {name:'Tam Hou', value:6}, {name:'Rui-Long', value:10}, {name:'Dong Xin', value:12}, 
        {name:'He Yu', value:20}, {name:'Xiang-Li', value:12}, {name:'Wei-Yu', value:15}, {name:'Chen Zheng', value:14}, 
        {name:'Tian-Xing', value:15}, {name:'Yang-Fu', value:15}, {name:'Qing-Wen', value:18}, {name:'Yi-Xiao', value:18}]; 

        const svg = d3.select('#mainsvg');
        const width = +svg.attr('width');
        const height = +svg.attr('height');
        const margin = {top: 60, right: 30, bottom: 60, left: 150};
        const innerWidth = width - margin.left - margin.right;
        const innerHeight = height - margin.top - margin.bottom;

        const xScale = d3.scaleLinear()
        .domain([0, d3.max(data, d => d.value)])
        .range([0, innerWidth]);

        const yScale = d3.scaleBand()
        .domain( data.map(d => d.name) )
        .range([0, innerHeight])
        .padding(0.1);

        const g = svg.append('g').attr('id', 'maingroup')
        .attr('transform', `translate(${margin.left}, ${margin.top})`);

        const xAxis = d3.axisBottom(xScale);
        g.append('g').call(xAxis).attr('transform', `translate(${0}, ${innerHeight})`);

        const yAxis = d3.axisLeft(yScale);
        g.append('g').call(yAxis);

        d3.selectAll('.tick text').attr('font-size', '2em');
        g.append('text').text('Members of CSCG').attr('font-size', '3em')
        .attr('transform', `translate(${innerWidth/2}, ${0})`)
        .attr('text-anchor', 'middle');

        const rects = g.selectAll('rect').data(data).join('rect')
        .attr('fill', 'green').attr('opacity', 0.8)
        .attr('y', d => yScale(d.name)).attr('height', yScale.bandwidth());

        const texts = g.selectAll('.datatext').data(data).join('text')
        .attr('class', 'datatext').text(d => d.value)
        .attr('y', d => yScale(d.name) + 5 + yScale.bandwidth() / 2)

        var formatPercent = d3.format(".2f");

        (async () => {
          while(true){
            data.forEach(d => {
                d.value = Math.random() * 20;
            });
            let transition = d3.transition().ease(d3.easeCubic)//.ease(d3.easeLinear) // we can optionally alter 'ease'; 
            .duration(1000);
            rects.transition(transition) 
            .attr('width', d => xScale(d.value))
            .attr('fill', () => d3.interpolateRainbow(Math.random()));
            texts.transition(transition)
            .attr('x', d => xScale(d.value))
            .tween("text", function(d) {
                var i = d3.interpolate(this.textContent, d.value);
                return function(t) {
                    this.textContent = formatPercent(i(t));
                };
            });
            await transition.end();
          }
        })()
    </script>
  </body>
</html>